<!--
 * @Author: liujm
 * @Date: 2022-10-12 17:40:22
 * @Description: 发送按钮调用弹框
-->
<template>
  <div class="jdf-send-org">
    <el-dialog
      v-bind="dialogAttrs"
      :width="dialogWidth"
      :title="dialogTitle"
      :visible.sync="dialogVisible"
      :modal-append-to-body="modalAppendToBody"
      :append-to-body="appendToBody"
      top="10vh"
      custom-class="jdf-send-tracking-dialog"
      v-el-drag-dialog="true"
      @close="hide"
    >
      <template>
        <el-table
          ref="sendTable"
          :data="tableData"
          :span-method="objectSpanMethod"
          style="width: 100%; margin-top: 20px">
          <el-table-column
            v-for="(item) in cols"
            :key="item">
            <template slot-scope="scope">
              <div :set="res=scope.row[item]" >
                <jdf-select-org
                  :data="res.orgs || []"
                  :tree-title="treeTitle"
                  :filterable="filterable"
                  :multiple="isMultiple(res.multiple)"
                  :orgTitle="res.orgName"
                  :class="{[res.class]: res.rowspan > 1, 'jdf-send-org-no-filterable': !filterable }"
                  :ref="`sendOrg${scope.$index}${item}`"
                  :selected-datas.sync="selectedList">
                </jdf-select-org>
              </div>
            </template>
          </el-table-column>
        </el-table>
        <div class="pj-send-form-file" v-if="isSetBack">
          <span @click="open">查看背靠背附件</span>
          <el-tooltip
            content="如附件关联了对应组织，则附件会发送给对应组织。如附件无关联任何组织，则此附件不会发送出去。"
            placement="left-start"
            effect="light"
            :visible-arrow="false"
            popper-class="jdf-popper-tooltip"
          >
            <i class="jdf-tooltip-icon el-icon-info ml5"></i>
          </el-tooltip>
        </div>
        <div class="send-orgs-name">
          <span class="label">{{dialogTitle}}范围：</span>
          <span>{{ setDeptOrder(selectedList, sendData).join('，') }}</span>
        </div>
        <!-- 发送选项 -->
        <div class='head-office-select'>
          <el-checkbox-group v-model="sendChecked">
            <div v-for="(item, index) in sendOptions" :key="index">
              <el-checkbox :label="item.value" :disabled="item.disabled">
                <span @click.prevent>{{ item.label }}</span>
              </el-checkbox>
            </div>
          </el-checkbox-group>
        </div>
        <!--  -->
        <div class="flex send-orgs-name"  v-if="!isSetBack">
          <template>
            <el-tree
              ref="fileTree"
              v-if="!isEmpty(treeData)"
              class="pj-send-form-tree"
              :data="treeData"
              show-checkbox
              node-key="fileId"
              default-expand-all
              expand-on-click-node
              :check-on-click-node="false"
              :props="defaultProps"
              @check="handleCheckChange"
            >
              <template slot-scope="{ data, node }">
                <span class="custom-tree-node-title" :title="node.label">
                  {{ data.fileName }}
                </span>
              </template>
            </el-tree>
          </template>
          <div class="head-office-select">
            <el-checkbox-group v-model="checkedHeadOffice" @change="changeHeadOffice">
              <div v-for="(item, index) in headOffice" :key="index">
                <el-checkbox :label="item.orgCode">
                  <span @click.prevent>{{ item.orgName }}</span>
                </el-checkbox>
              </div>
            </el-checkbox-group>
          </div>
        </div>
      </template>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" :loading="sendLoading" @click="confirm">确 定</el-button>
        <el-button @click="hide">取 消</el-button>
      </div>
    </el-dialog>
    <jdf-back-to-back
      v-if="backVisible"
      :visible.sync="backVisible"
      :piid="piid"
      :taskId='taskId'
      :biz-file-list="files"
      :send-org-list="backToBackOrgs"
      ref="backToBack"
    >
    </jdf-back-to-back>
  </div>
</template>
<script>
import {
  intersectionBy,
  isEmpty,
  mapKeys,
  cloneDeep,
  pick,
  uniqBy,
  flatMap,
  transform,
  map
} from 'lodash-es';
import { isEmptyStr } from 'jdf-util';
import { OrgResultTypeEnum, SendService, TransService } from 'jdf-jssdk';
import { alertErrorMsg, message, messageTipConfirm } from '@/api/utils/pc-message';
import settings from '@/settings/settings';
import { bizServiceURL } from '@/api/utils/constants';
import { sendTypesEnum } from '@/utils/enum';
import setDeptOrder from '@/utils/setDeptOrder';

export default {
  name: 'send-form',
  props: {
    filterable: Boolean,
    visible: Boolean,
    // 流程实例id
    piid: String,
    // 任务实例id
    taskId: String,
    // 流程模板code
    templateName: String,
    // 文件编号
    docNumber: String,
    data: {
      type: Array,
      default: () => [],
    },
    selectedDatas: {
      type: Array,
      default: () => [],
    },
    // 主抄送行数
    rows: {
      type: Number,
      default: 1,
    },
    // 每行列数
    cols: {
      type: Number,
      default: 1,
    },
    dialogTitle: {
      type: String,
      default: '发送',
    },
    treeTitle: {
      type: String,
      default: '可选',
    },
    // dialog宽度
    dialogWidth: {
      type: String,
      default: '1340px',
    },
    // 遮罩层是否插入至 body 元素上，若为 false，则遮罩层会插入至 Dialog 的父元素上
    modalAppendToBody: {
      type: Boolean,
      default: true,
    },
    // Dialog 自身是否插入至 body 元素上。嵌套的 Dialog 必须指定该属性并赋值为 true
    appendToBody: {
      type: Boolean,
      default: false,
    },
    // 确认前事件
    beforeClose: Function,
    // 附件列表
    files: Array,
    leaderList: {
      type: Array,
      default: () => []
    },
    // 流程模板id
    processDefinitionKey: String,
    // 是否设置过背靠背附件
    isSetBack: {
      type: Boolean,
      default: false,
    },
  },
  watch: {
    visible: {
      handler(val) {
        val && this.show();
      },
      immediate: true
    }
  },
  data() {
    return {
      setDeptOrder,
      backVisible: false,
      dialogVisible: false,
      isEmpty,
      dialogAttrs: settings.dialogAttrs,
      selectedList: [],
      tableData: [],
      // 选择的发送类型
      checkTypes: [],
      checkList: [],
      fileCheck: [],
      checkAll: false,
      isIndeterminate: false,
      sendLoading: false,
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      // 发送类型选择树
      treeData: [],
      // 公司主体
      headOffice: [],
      // 选择的公司主体
      checkedHeadOffice: [],
      sendData: [],
      sendChecked: ['checkDraftPersonnel'],
      sendOptions: [
        {
          value: 'allPersonnel',
          label: '发送公告供所有员工查询'
        },
        {
          value: 'printPersonnel',
          label: '发送文印人员打印'
        },
        {
          value: 'checkDraftPersonnel',
          label: '发送拟稿人复核'
        }
      ]
    };
  },
  computed: {
    /**
     * 实际发送的单位
     */
    realSendSelected() {
      const { checkedHeadOffice } = this;
      if (isEmpty(checkedHeadOffice)) {
        return this.selectedList;
      }
      const [checked] = checkedHeadOffice;
      const headOffice = this.headOffice.find(t => t.orgCode === checked);
      return uniqBy([...this.selectedList, headOffice], 'orgCode');
    },
    /**
     * 背靠背附件组织
     */
    backToBackOrgs() {
      return this.selectedList.filter((t) => !t.loginName);
    },
  },
  mounted() {
    this.tableData = cloneDeep(this.data).map((t) => {
      mapKeys(t, (v, k) => {
        // eslint-disable-next-line no-param-reassign
        t[k] = this.setResData(v);
      });
      return {
        ...t,
      };
    });
  },
  methods: {
    /**
     * 隐藏窗口
     */
    hide() {
      this.dialogVisible = false;
      this.$emit('update:visible', false);
    },
    /**
     * 打开窗口
     */
    show() {
      this.sendData = flatMap(cloneDeep(this.data).map((t) => transform(t, (result, v) => {
        result.push({
          ...v,
          orgs: map(v.orgs, (m => ({
            ...m,
            unityKey: m.type === OrgResultTypeEnum.ORG ? m.orgCode : m.id,
          })))
        });
      }, [])));
      this.dialogVisible = true;
      const leaderList = this.leaderList.map(t => ({
        ...t.userIdentityObj,
        ...t,
        orgId: `${t.userIdentityObj.orgId}`,
        pkId: t.id,
      }));
      this.selectedList = map(cloneDeep([...this.selectedDatas, ...leaderList]), (v => ({
        ...v,
        unityKey: v.type === OrgResultTypeEnum.ORG ? v.orgCode : `${v.id}`,
      })));
      this.treeData = [
        {
          fileName: '发送附件',
          children: [...this.files]
        }
      ];
      const config = sendTypesEnum.find(t => t.nodes.includes(this.processDefinitionKey));
      config && (this.headOffice = config.headOffice);
      this.$nextTick(() => {
        this.$refs.sendTable.doLayout();
        !this.isSetBack && this.$refs.fileTree.setCheckedKeys(map(this.files, 'fileId'));
      });
    },
    /**
     * 查看背靠背附件
     */
    open() {
      this.backVisible = true;
      // this.$refs.backToBack.show();
    },
    /**
     * 选择发送类型事件
     */
    handleCheckChange(data, { checkedKeys }) {
      this.checkTypes = checkedKeys;
    },
    /**
     * 选择公司主体后事件-单选
     * @param {Array} val 选择的值
     */
    changeHeadOffice(val) {
      if (isEmpty(val)) {
        return;
      }
      this.checkedHeadOffice = [val.at(-1)];
    },
    /**
     * 保存背靠背附件组织信息
     */
    saveOrgFileList() {
      if (this.isSetBack) {
        return {};
      }
      // 获取所有的部门
      // 获取选中的附件list
      const fileList = this.$refs.fileTree.getCheckedNodes(true);
      const param = isEmpty(this.files) ? [] : map(this.realSendSelected, (v) => ({
        orgFileVoList: map(fileList, t => ({
          fileId: t.fileId,
          orgCode: v.orgCode,
          fileName: t.fileName,
          orgName: v.orgName,
        }))
      }));
      return new TransService(bizServiceURL).saveOrgFile(this.piid, flatMap(param, 'orgFileVoList'));
    },
    /**
     * 确认事件
     */
    async confirm() {
      if (isEmpty(this.realSendSelected)) {
        message('请选择发送范围！', 'warning');
        return;
      }
      if (isEmptyStr(this.docNumber)) {
        message('请填写文件编号！', 'warning');
        return;
      }
      // 保存附件背靠背关系
      await this.saveOrgFileList();
      const realSendSelected = this.realSendSelected.map(t => pick(t, [
        'parentName',
        'orgCode',
        'orgName',
        'orgDeepId',
        'isGateway',
        'type',
        'loginName',
        'permittedDocType'
      ]));
      const { code, message: msgStr } = await new SendService(bizServiceURL).checkToSend(this.piid, realSendSelected);
      if (code === '-1') {
        message(msgStr, 'warning');
        return;
      }
      if (code === '-2') {
        messageTipConfirm(
          msgStr,
          () => this.doSend(realSendSelected),
          null,
          '发送确认',
          { dangerouslyUseHTMLString: true, customClass: 'send-message-box' }
        );
        return;
      }
      this.doSend(realSendSelected);
    },
    /**
     * 执行发送操作
     */
    doSend(selectedList) {
      const tip = this.isSetBack ? '您已设置背靠背关联，是否确认将文件' : '是否确认将文件';
      // 获取发送员工查询等数据以及真是发送数据，目前只做展示然后关闭页面
      return messageTipConfirm(`${tip}发送至${setDeptOrder(this.realSendSelected, this.sendData).join('，')}`, async () => {
        try {
          this.sendLoading = true;
          // 先执行发送方法，发送成功后再执行发送窗口关闭前置
          await new SendService(bizServiceURL).saveSendData(this.piid, selectedList);
          await this.beforeClose?.(selectedList);
          message('发送成功');
          this.hide();
          this.$emit('success');
        } catch (error) {
          alertErrorMsg(error);
        } finally {
          this.sendLoading = false;
        }
      }, null, '发送确认', {
        customClass: 'send-message-box'
      });
    },
    /**
     * 合并行事件
     */
    objectSpanMethod({
      row, columnIndex,
    }) {
      /**
       * 合并行、列的方法
       */
      const spanRowParam = (rowspan, colspan) => ({
        rowspan,
        colspan,
      });
      const res = row[columnIndex + 1] ?? {};
      const {
        rowspan = -1,
      } = res;
      if (rowspan > 0) {
        return spanRowParam(rowspan, 1);
      }
      if (rowspan === -1) {
        return spanRowParam(0, 0);
      }
      return spanRowParam(1, 1);
    },
    /**
     * 获取已选值
     */
    getSelectedDatas(orgs) {
      return intersectionBy(this.selectedList, orgs, 'unityKey');
    },
    /**
     * 组装表格数据
     */
    setResData(item) {
      return item ? {
        ...item,
        class: `jdf-send-org-span-row-${item.rowspan}`,
        selectDatas: this.getSelectedDatas(item.orgs),
      } : {
        rowspan: -1,
      };
    },
    /**
     * 是否多选
     */
    isMultiple(multiple) {
      return multiple ?? true;
    },
  },
};
</script>
<style lang="scss">
@import '@/assets/style/variables.scss';

.pj-send-form-file {
  color: $main-color;
  cursor: pointer;
  padding-left: 12px;
  margin-bottom: 5px;
}

.send-orgs-name {
  margin-top: 18px;
  padding-left: 12px;
  margin-bottom: 5px;
}
.send-orgs-fileName {
  padding-left: 9px;
  margin-bottom: 5px;
  .el-tree-node__content {
    background-color: transparent !important;
  }
  .pj-send-form-tree .el-tree-node {
    padding: 0 3px;
    width: 700px;
    word-break: break-all;
    overflow-wrap: break-word;
    white-space: wrap;
  }

  .pj-send-form-tree .el-icon-caret-right {
    display: none;

  }
}

.head-office-select {
  padding: 12px 12px 0 12px;
  margin-bottom: 1px;
  .el-checkbox {
    line-height: 26px;
    .el-checkbox__label {
      padding-left: 8px;
      span {
        display: block;
        line-height: 26px;
      }
    }
  }
}
</style>
